#include "TinyXMLSerializationTest.h"

#include "CBL_FolderFileSystem.h"
#include "CBL_TinyXMLSerializer.h"
#include <string>
#include "CBL_Profile.h"

// -----------------------------------------------------------------------------

class CTestClass2 : public Cb::ISerializeable
{
public:
    
	CTestClass2() 
        : m_BoolValue(false)
        , m_UByteValue(0)
        , m_UShortValue(0)
        , m_UIntValue(0)
        , m_UInt64Value(0)
        , m_FloatValue(0)
        , m_DoubleValue(0)
        , m_ByteValue(0)
        , m_ShortValue(0)
        , m_IntValue(0)
        , m_Int64Value(0)
        , m_TestValue(0)
    {}
    
    virtual void SERIALIZE_FUNCTION()
    {
    	_rSerializer.Serialize(m_TestValue, 	"TestValue");
    	_rSerializer.Serialize(m_BoolValue, 	"BoolValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_UByteValue, 	"UByteValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_UShortValue, 	"UShortValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_UIntValue, 	"UIntValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_UInt64Value, 	"UInt64Value",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_FloatValue, 	"FloatValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_DoubleValue, 	"DoubleValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_StringValue,	"StringValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_ByteValue, 	"ByteValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_ShortValue, 	"ShortValue",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_IntValue, 	  	"IntValue",		Cb::CTinyXMLSerializer::FlagInlineBlockData);
        _rSerializer.Serialize(m_Int64Value,	"Int64Value",	Cb::CTinyXMLSerializer::FlagInlineBlockData);
    }
    
public:

	bool   m_BoolValue;
	uint8  m_UByteValue;
	uint16 m_UShortValue;
	uint32 m_UIntValue;
	uint64 m_UInt64Value;
    
    float  m_FloatValue;
    double m_DoubleValue;
    
    std::string m_StringValue;
    
    int8  m_ByteValue;
	int16 m_ShortValue;
	int32 m_IntValue;
	int64 m_Int64Value;
    
    int8  m_TestValue;
};
  
// -----------------------------------------------------------------------------
  
class CTestClass : public Cb::ISerializeable
{
public:
    
	CTestClass() 
    	: m_BoolValue(false)
        , m_UByteValue(0)
        , m_UShortValue(0)
        , m_UIntValue(0)
        , m_UInt64Value(0)
        , m_FloatValue(0)
        , m_DoubleValue(0)
    {
    }
    
    virtual ~CTestClass() {}
    
    virtual void SERIALIZE_FUNCTION()
    {
    	_rSerializer.Serialize(m_BoolValue, 	"BoolValue");
        _rSerializer.Serialize(m_UByteValue, 	"UByteValue");
        _rSerializer.Serialize(m_UShortValue, 	"UShortValue");
        _rSerializer.Serialize(m_UIntValue, 	"UIntValue");
        _rSerializer.Serialize(m_UInt64Value, 	"UInt64Value");
        _rSerializer.Serialize(m_FloatValue, 	"FloatValue");
        _rSerializer.Serialize(m_DoubleValue, 	"DoubleValue");
        _rSerializer.Serialize(m_StringValue,	"StringValue");
        _rSerializer.Serialize(m_SubClass, 		"SubClass");
    }

public:

	bool   m_BoolValue;
	uint8  m_UByteValue;
	uint16 m_UShortValue;
	uint32 m_UIntValue;
	uint64 m_UInt64Value;
    
    float  m_FloatValue;
    double m_DoubleValue;
    
    std::string m_StringValue;
    CTestClass2 m_SubClass;
};

// -----------------------------------------------------------------------------

class CDerivedTestClass : public CTestClass
{
public:
    
    CDerivedTestClass() 
        : m_ByteValue(0)
        , m_ShortValue(0)
        , m_IntValue(0)
        , m_Int64Value(0)
    {}
    
    virtual ~CDerivedTestClass() {}
    
    virtual void SERIALIZE_FUNCTION()
    {
    	_rSerializer.SerializeBlockStart("BaseClass");
    	CTestClass::Serialize(_rSerializer);
    	_rSerializer.SerializeBlockEnd("BaseClass");
    
        _rSerializer.Serialize(m_ByteValue, 	"ByteValue");
    	_rSerializer.Serialize(m_ShortValue, 	"ShortValue");
    	_rSerializer.Serialize(m_IntValue, 	  	"IntValue");
    	_rSerializer.Serialize(m_Int64Value,	"Int64Value");
    }
    
public:
    
	int8  m_ByteValue;
	int16 m_ShortValue;
	int32 m_IntValue;
	int64 m_Int64Value;
};

// -----------------------------------------------------------------------------

const char* pTinyXMLTest = 
"<TestObject class=\"CDerivedTestClass\">"
	"<BaseClass>"
		"<BoolValue value=\"true\" />"
		"<!--<BoolValue value=\"false\"/>-->"
        "<UByteValue value = \"1\"/>"
        "<UShortValue  value= \"2\"/>"
        "<UIntValue value=\"3\"/>"
        "<UInt64Value value=\"4\"/>"
        "<FloatValue value=\"0.123\"/>"
        "<DoubleValue value=\"0.456\"/>"
        "<StringValue>Base</StringValue>"
		"<SubClass class=\"CTestClass2\" BoolValue=\"true\" UByteValue=\"1\" UShortValue=\"2\" UIntValue=\"3\" UInt64Value=\"4\" FloatValue=\"0.123\" DoubleValue=\"0.456\" StringValue=\"abc\" ByteValue=\"-1\" ShortValue=\"-2\" IntValue=\"-3\" Int64Value=\"-4\">"
			"<TestValue value=\"42\"/>"
        "</SubClass>"
    "</BaseClass>"
	"<ByteValue value=\"-1\"/>"
	"<ShortValue value=\"-2\"/>"
	"<IntValue value=\"-3\"/>"
	"<Int64Value value=\"-4\"/>"
"</TestObject>";

BEGIN_TEST_CASE_IMPLEMENTATION(CTinyXMLSerializationTest)
CB_PROFILE("TinyXML Testcase");

CDerivedTestClass TestObject;

/*Cb::CFolderFileSystem FileSystem("/Users/arnecls");
Cb::CTinyXMLSerializer Serializer(Cb::ISerializer::Writing, *(Cb::IFileSystem*)&FileSystem, "test.xml");
Serializer.Serialize(TestObject, "TestObject");*/

Cb::CTinyXMLSerializer BufferReader(Cb::ISerializer::Reading, pTinyXMLTest);
BufferReader.Serialize(TestObject, "TestObject");

CHECK(TestObject.m_BoolValue, 		 	"> TinyXML serialization for type bool failed.")
CHECK(TestObject.m_ByteValue   == -1, 	"> TinyXML serialization for type int8 failed.")
CHECK(TestObject.m_ShortValue  == -2, 	"> TinyXML serialization for type int16 failed.")
CHECK(TestObject.m_IntValue    == -3, 	"> TinyXML serialization for type int32 failed.")
CHECK(TestObject.m_Int64Value  == -4, 	"> TinyXML serialization for type int64 failed.")
CHECK(TestObject.m_UByteValue  == 1,  	"> TinyXML serialization for type uint8 (baseclass) failed.")
CHECK(TestObject.m_UShortValue == 2,	"> TinyXML serialization for type uint16 (baseclass) failed.")
CHECK(TestObject.m_UIntValue   == 3, 	"> TinyXML serialization for type uint32 (baseclass) failed.")
CHECK(TestObject.m_UInt64Value == 4, 	"> TinyXML serialization for type uint64 (baseclass) failed.")

CHECK(TestObject.m_SubClass.m_TestValue   == 42, 	"> TinyXML sublass serialization for type int8 failed.")
CHECK(TestObject.m_SubClass.m_BoolValue, 		 	"> TinyXML inline serialization for type bool failed.")
CHECK(TestObject.m_SubClass.m_ByteValue   == -1, 	"> TinyXML inline serialization for type int8 failed.")
CHECK(TestObject.m_SubClass.m_ShortValue  == -2, 	"> TinyXML inline serialization for type int16 failed.")
CHECK(TestObject.m_SubClass.m_IntValue    == -3, 	"> TinyXML inline serialization for type int32 failed.")
CHECK(TestObject.m_SubClass.m_Int64Value  == -4, 	"> TinyXML inline serialization for type int64 failed.")
CHECK(TestObject.m_SubClass.m_UByteValue  == 1,  	"> TinyXML inline serialization for type uint8 (baseclass) failed.")
CHECK(TestObject.m_SubClass.m_UShortValue == 2,		"> TinyXML inline serialization for type uint16 (baseclass) failed.")
CHECK(TestObject.m_SubClass.m_UIntValue   == 3, 	"> TinyXML inline serialization for type uint32 (baseclass) failed.")
CHECK(TestObject.m_SubClass.m_UInt64Value == 4, 	"> TinyXML inline serialization for type uint64 (baseclass) failed.")

CHECK(Cb::Math::AlmostEqual(TestObject.m_FloatValue, 0.123f), "> TinyXML serialization for type float failed.")
CHECK(Cb::Math::AlmostEqual(TestObject.m_DoubleValue, 0.456),	"> TinyXML serialization for type double failed.")

Cb::CTinyXMLSerializer BufferWriter(Cb::ISerializer::Writing);
BufferWriter.Serialize(TestObject, "TestObject");

Cb::Memory::CAutoBuffer<char> WriteBuffer = BufferWriter.Flush();

CDerivedTestClass TestObject2;

Cb::CTinyXMLSerializer BufferReader2(Cb::ISerializer::Reading, WriteBuffer.GetBuffer());
BufferReader2.Serialize(TestObject2, "TestObject");

CHECK(TestObject.m_BoolValue   == TestObject2.m_BoolValue, 		"> TinyXML reserialization for type bool failed.")
CHECK(TestObject.m_ByteValue   == TestObject2.m_ByteValue,  	"> TinyXML reserialization for type int8 failed.")
CHECK(TestObject.m_ShortValue  == TestObject2.m_ShortValue, 	"> TinyXML reserialization for type int16 failed.")
CHECK(TestObject.m_IntValue    == TestObject2.m_IntValue, 	 	"> TinyXML reserialization for type int32 failed.")
CHECK(TestObject.m_Int64Value  == TestObject2.m_Int64Value, 	"> TinyXML reserialization for type int64 failed.")
CHECK(TestObject.m_UByteValue  == TestObject2.m_UByteValue,  	"> TinyXML reserialization for type uint8 (baseclass) failed.")
CHECK(TestObject.m_UShortValue == TestObject2.m_UShortValue, 	"> TinyXML reserialization for type uint16 (baseclass) failed.")
CHECK(TestObject.m_UIntValue   == TestObject2.m_UIntValue, 	 	"> TinyXML reserialization for type uint32 (baseclass) failed.")
CHECK(TestObject.m_UInt64Value == TestObject2.m_UInt64Value, 	"> TinyXML reserialization for type uint64 (baseclass) failed.")

CHECK(TestObject.m_SubClass.m_TestValue   == TestObject2.m_SubClass.m_TestValue, 	"> TinyXML subclass reserialization for type int8 failed.")
CHECK(TestObject.m_SubClass.m_BoolValue   == TestObject2.m_SubClass.m_BoolValue, 	"> TinyXML inline reserialization for type bool failed.")
CHECK(TestObject.m_SubClass.m_ByteValue   == TestObject2.m_SubClass.m_ByteValue,  	"> TinyXML inline reserialization for type int8 failed.")
CHECK(TestObject.m_SubClass.m_ShortValue  == TestObject2.m_SubClass.m_ShortValue, 	"> TinyXML inline reserialization for type int16 failed.")
CHECK(TestObject.m_SubClass.m_IntValue    == TestObject2.m_SubClass.m_IntValue, 	"> TinyXML inline reserialization for type int32 failed.")
CHECK(TestObject.m_SubClass.m_Int64Value  == TestObject2.m_SubClass.m_Int64Value, 	"> TinyXML inline reserialization for type int64 failed.")
CHECK(TestObject.m_SubClass.m_UByteValue  == TestObject2.m_SubClass.m_UByteValue,  	"> TinyXML inline reserialization for type uint8 (baseclass) failed.")
CHECK(TestObject.m_SubClass.m_UShortValue == TestObject2.m_SubClass.m_UShortValue, 	"> TinyXML inline reserialization for type uint16 (baseclass) failed.")
CHECK(TestObject.m_SubClass.m_UIntValue   == TestObject2.m_SubClass.m_UIntValue, 	"> TinyXML inline reserialization for type uint32 (baseclass) failed.")
CHECK(TestObject.m_SubClass.m_UInt64Value == TestObject2.m_SubClass.m_UInt64Value, 	"> TinyXML inline reserialization for type uint64 (baseclass) failed.")

CHECK(Cb::Math::AlmostEqual(TestObject.m_FloatValue, TestObject2.m_FloatValue), 	"> TinyXML reserialization for type float failed.")
CHECK(Cb::Math::AlmostEqual(TestObject.m_DoubleValue, TestObject2.m_DoubleValue),	"> TinyXML reserialization for type double failed.")

END_TEST_CASE_IMPLEMENTATION

















